package cn.wp.common.core.module.login;

import cn.wp.common.core.authentication.AuthenticationContext;
import cn.wp.common.core.authentication.AuthenticationInfo;
import cn.wp.common.core.authentication.Token;
import cn.wp.common.core.authentication.UsernamePasswordToken;
import cn.wp.common.core.authentication.util.TokenUtil;
import cn.wp.common.core.exception.WpAuthenticationException;
import cn.wp.common.core.util.BCryptPasswordEncoder;

public abstract class GenericLoginService implements LoginService {

    @Override
    public AuthenticationInfo login(String username, String password){
        UsernamePasswordToken usernamePasswordToken = this.createUsernamePasswordToken(username);
        if(usernamePasswordToken == null){
            WpAuthenticationException ex = new WpAuthenticationException("用户不存在");
            onLoginFailure(username,ex);
            throw ex;
        }
        boolean usernameEQ = username.equals(usernamePasswordToken.getUsername());
        boolean passwordEQ = BCryptPasswordEncoder.getInstance().matches(password,usernamePasswordToken.getPassword());
        AuthenticationInfo authenticationInfo = null;
        if(usernameEQ && passwordEQ){
            try{
                authenticationInfo = loadUserByUsername(username);
            }catch (WpAuthenticationException ex){
                onLoginFailure(username,ex);
                throw ex;
            }

            if(authenticationInfo == null){
                WpAuthenticationException ex = new WpAuthenticationException("用户不存在");
                onLoginFailure(username,ex);
                throw ex;
            }

            Token token = TokenUtil.self().createToken();
            authenticationInfo.setToken(token.getTokenValue());
            // 添加到缓存
            AuthenticationContext.self().add(token,authenticationInfo);
            // 登录成功后续事件处理
            onLoginSuccess(authenticationInfo);
            return authenticationInfo;
        }else{
            WpAuthenticationException ex = new WpAuthenticationException("密码不匹配");
            onLoginFailure(username,ex);
            throw ex;
        }
    }

    @Override
    public boolean logout(){
        AuthenticationInfo authenticationInfo = AuthenticationContext.self().currentUser();
        AuthenticationContext.self().remove();
        onLogoutSuccess(authenticationInfo);
        return true;
    }

    /**
     * 获取校验token
     * @param username
     * @return
     */
    public abstract UsernamePasswordToken createUsernamePasswordToken(String username);

    /**
     * 根据用户名查询用户信息
     * @param username
     * @return
     */
    public abstract AuthenticationInfo loadUserByUsername(String username);

    /**
     * 登录成功回调
     * @param authenticationInfo
     */
    public abstract void onLoginSuccess(AuthenticationInfo authenticationInfo);

    /**
     * 登录失败回调
     * @param username
     * @param ex
     */
    public abstract void onLoginFailure(String username,WpAuthenticationException ex);


    /**
     * 退出登录成功回调
     * @param authenticationInfo
     */
    public abstract void onLogoutSuccess(AuthenticationInfo authenticationInfo);

}